home *** CD-ROM | disk | FTP | other *** search
/ Amiga Games Extra 1996 September / Amiga Games Extra CD-ROM 9-1996.iso / userbox / publicdomain / vim-4.2 / src / cmdcmds.c < prev    next >
C/C++ Source or Header  |  1996-06-17  |  28KB  |  1,236 lines

  1. /* vi:set ts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved        by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  */
  8.  
  9. /*
  10.  * cmdcmds.c: functions for command line commands
  11.  */
  12.  
  13. #include "vim.h"
  14. #include "globals.h"
  15. #include "proto.h"
  16. #include "option.h"
  17.  
  18. #ifdef USE_TMPNAM
  19. # define mktemp(a)    tmpnam(a)
  20. #endif
  21.  
  22. extern char        *mktemp __ARGS((char *));
  23.  
  24. #ifdef OS2
  25. static void check_tmpenv __ARGS((void));
  26. #endif
  27.  
  28. #ifdef VIMINFO
  29. static char_u *viminfo_filename __ARGS((char_u     *));
  30. static void do_viminfo __ARGS((FILE *fp_in, FILE *fp_out, int want_info, int want_marks, int force_read));
  31. static int read_viminfo_up_to_marks __ARGS((char_u *line, FILE *fp, int force));
  32. #endif /* VIMINFO */
  33.  
  34.     void
  35. do_ascii()
  36. {
  37.     int        c;
  38.     char    buf1[20];
  39.     char    buf2[20];
  40.     char_u    buf3[3];
  41.  
  42.     c = gchar_cursor();
  43.     if (c == NL)            /* NUL is stored as NL */
  44.         c = NUL;
  45.     if (isprintchar(c) && (c < ' ' || c > '~'))
  46.     {
  47.         transchar_nonprint(buf3, c);
  48.         sprintf(buf1, "  <%s>", (char *)buf3);
  49.     }
  50.     else
  51.         buf1[0] = NUL;
  52.     if (c >= 0x80)
  53.         sprintf(buf2, "  <M-%s>", transchar(c & 0x7f));
  54.     else
  55.         buf2[0] = NUL;
  56.     sprintf((char *)IObuff, "<%s>%s%s  %d,  Hex %02x,  Octal %03o",
  57.                                            transchar(c), buf1, buf2, c, c, c);
  58.     msg(IObuff);
  59. }
  60.  
  61. /*
  62.  * align text:
  63.  * type = -1  left aligned
  64.  * type = 0   centered
  65.  * type = 1   right aligned
  66.  */
  67.     void
  68. do_align(start, end, width, type)
  69.     linenr_t    start;
  70.     linenr_t    end;
  71.     int            width;
  72.     int            type;
  73. {
  74.     FPOS    pos;
  75.     int        len;
  76.     int        indent = 0;
  77.     int        new_indent = 0;            /* init for GCC */
  78.     char_u    *first;
  79.     char_u    *last;
  80.     int        save;
  81.  
  82. #ifdef RIGHTLEFT
  83.     if (curwin->w_p_rl)
  84.         type = -type;    /* switch left and right aligning */
  85. #endif
  86.  
  87.     pos = curwin->w_cursor;
  88.     if (type == -1)        /* left align: width is used for new indent */
  89.     {
  90.         if (width >= 0)
  91.             indent = width;
  92.     }
  93.     else
  94.     {
  95.         /*
  96.          * if 'textwidth' set, use it
  97.          * else if 'wrapmargin' set, use it
  98.          * if invalid value, use 80
  99.          */
  100.         if (width <= 0)
  101.             width = curbuf->b_p_tw;
  102.         if (width == 0 && curbuf->b_p_wm > 0)
  103.             width = Columns - curbuf->b_p_wm;
  104.         if (width <= 0)
  105.             width = 80;
  106.     }
  107.  
  108.     if (u_save((linenr_t)(start - 1), (linenr_t)(end + 1)) == FAIL)
  109.         return;
  110.     for (curwin->w_cursor.lnum = start;
  111.                         curwin->w_cursor.lnum <= end; ++curwin->w_cursor.lnum)
  112.     {
  113.             /* find the first non-blank character */
  114.         first = skipwhite(ml_get_curline());
  115.             /* find the character after the last non-blank character */
  116.         for (last = first + STRLEN(first);
  117.                                 last > first && vim_iswhite(last[-1]); --last)
  118.             ;
  119.         save = *last;
  120.         *last = NUL;
  121.         len = linetabsize(first);                    /* get line length */
  122.         *last = save;
  123.         if (len == 0)                                /* skip blank lines */
  124.             continue;
  125.         switch (type)
  126.         {
  127.             case -1:    new_indent = indent;            /* left align */
  128.                         break;
  129.             case 0:        new_indent = (width - len) / 2;    /* center */
  130.                         break;
  131.             case 1:        new_indent = width - len;        /* right align */
  132.                         break;
  133.         }
  134.         if (new_indent < 0)
  135.             new_indent = 0;
  136.         set_indent(new_indent, TRUE);            /* set indent */
  137.     }
  138.     curwin->w_cursor = pos;
  139.     beginline(TRUE);
  140.     updateScreen(NOT_VALID);
  141. }
  142.  
  143.     void
  144. do_retab(start, end, new_ts, force)
  145.     linenr_t    start;
  146.     linenr_t    end;
  147.     int            new_ts;
  148.     int            force;
  149. {
  150.     linenr_t    lnum;
  151.     int            got_tab = FALSE;
  152.     long        num_spaces = 0;
  153.     long        num_tabs;
  154.     long        len;
  155.     long        col;
  156.     long        vcol;
  157.     long        start_col = 0;            /* For start of white-space string */
  158.     long        start_vcol = 0;            /* For start of white-space string */
  159.     int            temp;
  160.     long        old_len;
  161.     char_u        *ptr;
  162.     char_u        *new_line = (char_u *)1;    /* init to non-NULL */
  163.     int            did_something = FALSE;
  164.     int            did_undo;                /* called u_save for current line */
  165.  
  166.     if (new_ts == 0)
  167.         new_ts = curbuf->b_p_ts;
  168.     for (lnum = start; !got_int && lnum <= end; ++lnum)
  169.     {
  170.         ptr = ml_get(lnum);
  171.         col = 0;
  172.         vcol = 0;
  173.         did_undo = FALSE;
  174.         for (;;)
  175.         {
  176.             if (vim_iswhite(ptr[col]))
  177.             {
  178.                 if (!got_tab && num_spaces == 0)
  179.                 {
  180.                     /* First consecutive white-space */
  181.                     start_vcol = vcol;
  182.                     start_col = col;
  183.                 }
  184.                 if (ptr[col] == ' ')
  185.                     num_spaces++;
  186.                 else
  187.                     got_tab = TRUE;
  188.             }
  189.             else
  190.             {
  191.                 if (got_tab || (force && num_spaces > 1))
  192.                 {
  193.                     /* Retabulate this string of white-space */
  194.  
  195.                     /* len is virtual length of white string */
  196.                     len = num_spaces = vcol - start_vcol;
  197.                     num_tabs = 0;
  198.                     if (!curbuf->b_p_et)
  199.                     {
  200.                         temp = new_ts - (start_vcol % new_ts);
  201.                         if (num_spaces >= temp)
  202.                         {
  203.                             num_spaces -= temp;
  204.                             num_tabs++;
  205.                         }
  206.                         num_tabs += num_spaces / new_ts;
  207.                         num_spaces -= (num_spaces / new_ts) * new_ts;
  208.                     }
  209.                     if (curbuf->b_p_et || got_tab ||
  210.                                         (num_spaces + num_tabs < len))
  211.                     {
  212.                         if (did_undo == FALSE)
  213.                         {
  214.                             did_undo = TRUE;
  215.                             if (u_save((linenr_t)(lnum - 1),
  216.                                                 (linenr_t)(lnum + 1)) == FAIL)
  217.                             {
  218.                                 new_line = NULL;        /* flag out-of-memory */
  219.                                 break;
  220.                             }
  221.                         }
  222.  
  223.                         /* len is actual number of white characters used */
  224.                         len = num_spaces + num_tabs;
  225.                         old_len = STRLEN(ptr);
  226.                         new_line = lalloc(old_len - col + start_col + len + 1,
  227.                                                                         TRUE);
  228.                         if (new_line == NULL)
  229.                             break;
  230.                         if (start_col > 0)
  231.                             vim_memmove(new_line, ptr, (size_t)start_col);
  232.                         vim_memmove(new_line + start_col + len,
  233.                                       ptr + col, (size_t)(old_len - col + 1));
  234.                         ptr = new_line + start_col;
  235.                         for (col = 0; col < len; col++)
  236.                             ptr[col] = (col < num_tabs) ? '\t' : ' ';
  237.                         ml_replace(lnum, new_line, FALSE);
  238.                         did_something = TRUE;
  239.                         ptr = new_line;
  240.                         col = start_col + len;
  241.                     }
  242.                 }
  243.                 got_tab = FALSE;
  244.                 num_spaces = 0;
  245.             }
  246.             if (ptr[col] == NUL)
  247.                 break;
  248.             vcol += chartabsize(ptr[col++], (colnr_t)vcol);
  249.         }
  250.         if (new_line == NULL)                /* out of memory */
  251.             break;
  252.         line_breakcheck();
  253.     }
  254.     if (got_int)
  255.         emsg(e_interr);
  256.     if (did_something)
  257.         CHANGED;
  258.     curbuf->b_p_ts = new_ts;
  259.     coladvance(curwin->w_curswant);
  260. }
  261.  
  262. /*
  263.  * :move command - move lines line1-line2 to line n
  264.  *
  265.  * return FAIL for failure, OK otherwise
  266.  */
  267.     int
  268. do_move(line1, line2, n)
  269.     linenr_t    line1;
  270.     linenr_t    line2;
  271.     linenr_t    n;
  272. {
  273.     char_u        *str;
  274.     linenr_t    l;
  275.     linenr_t    extra;        /* Num lines added before line1 */
  276.     linenr_t    num_lines;    /* Num lines moved */
  277.     linenr_t    last_line;    /* Last line in file after adding new text */
  278.     int            has_mark;
  279.  
  280.     if (n >= line1 && n < line2)
  281.     {
  282.         EMSG("Move lines into themselves");
  283.         return FAIL;
  284.     }
  285.  
  286.     num_lines = line2 - line1 + 1;
  287.  
  288.     /*
  289.      * First we copy the old text to its new location -- webb
  290.      */
  291.     if (u_save(n, n + 1) == FAIL)
  292.         return FAIL;
  293.     for (extra = 0, l = line1; l <= line2; l++)
  294.     {
  295.         str = strsave(ml_get(l + extra));
  296.         if (str != NULL)
  297.         {
  298.             has_mark = ml_has_mark(l + extra);
  299.             ml_append(n + l - line1, str, (colnr_t)0, FALSE);
  300.             vim_free(str);
  301.             if (has_mark)
  302.                 ml_setmarked(n + l - line1 + 1);
  303.             if (n < line1)
  304.                 extra++;
  305.         }
  306.     }
  307.  
  308.     /*
  309.      * Now we must be careful adjusting our marks so that we don't overlap our
  310.      * mark_adjust() calls.
  311.      *
  312.      * We adjust the marks within the old text so that they refer to the
  313.      * last lines of the file (temporarily), because we know no other marks
  314.      * will be set there since these line numbers did not exist until we added
  315.      * our new lines.
  316.      *
  317.      * Then we adjust the marks on lines between the old and new text positions
  318.      * (either forwards or backwards).
  319.      *
  320.      * And Finally we adjust the marks we put at the end of the file back to
  321.      * their final destination at the new text position -- webb
  322.      */
  323.     last_line = curbuf->b_ml.ml_line_count;
  324.     mark_adjust(line1, line2, last_line - line2, 0L);
  325.     if (n >= line2)
  326.         mark_adjust(line2 + 1, n, -num_lines, 0L);
  327.     else
  328.         mark_adjust(n + 1, line1 - 1, num_lines, 0L);
  329.     mark_adjust(last_line - num_lines + 1, last_line,
  330.                                                 -(last_line - n - extra), 0L);
  331.     
  332.     /*
  333.      * Now we delete the original text -- webb
  334.      */
  335.     if (u_save(line1 + extra - 1, line2 + extra + 1) == FAIL)
  336.         return FAIL;
  337.  
  338.     for (l = line1; l <= line2; l++)
  339.         ml_delete(line1 + extra, TRUE);
  340.  
  341.     CHANGED;
  342.     if (!global_busy && num_lines > p_report)
  343.         smsg((char_u *)"%ld line%s moved", num_lines, plural(num_lines));
  344.     return OK;
  345. }
  346.  
  347. /*
  348.  * :copy command - copy lines line1-line2 to line n
  349.  */
  350.     void
  351. do_copy(line1, line2, n)
  352.     linenr_t    line1;
  353.     linenr_t    line2;
  354.     linenr_t    n;
  355. {
  356.     linenr_t        lnum;
  357.     char_u            *p;
  358.  
  359.     mark_adjust(n + 1, MAXLNUM, line2 - line1 + 1, 0L);
  360.  
  361.     /*
  362.      * there are three situations:
  363.      * 1. destination is above line1
  364.      * 2. destination is between line1 and line2
  365.      * 3. destination is below line2
  366.      *
  367.      * n = destination (when starting)
  368.      * curwin->w_cursor.lnum = destination (while copying)
  369.      * line1 = start of source (while copying)
  370.      * line2 = end of source (while copying)
  371.      */
  372.     if (u_save(n, n + 1) == FAIL)
  373.         return;
  374.     curwin->w_cursor.lnum = n;
  375.     lnum = line2 - line1 + 1;
  376.     while (line1 <= line2)
  377.     {
  378.         /* need to use strsave() because the line will be unlocked
  379.             within ml_append */
  380.         p = strsave(ml_get(line1));
  381.         if (p != NULL)
  382.         {
  383.             ml_append(curwin->w_cursor.lnum, p, (colnr_t)0, FALSE);
  384.             vim_free(p);
  385.         }
  386.                 /* situation 2: skip already copied lines */
  387.         if (line1 == n)
  388.             line1 = curwin->w_cursor.lnum;
  389.         ++line1;
  390.         if (curwin->w_cursor.lnum < line1)
  391.             ++line1;
  392.         if (curwin->w_cursor.lnum < line2)
  393.             ++line2;
  394.         ++curwin->w_cursor.lnum;
  395.     }
  396.     CHANGED;
  397.     msgmore((long)lnum);
  398. }
  399.  
  400. /*
  401.  * Handle the ":!cmd" command.  Also for ":r !cmd" and ":w !cmd"
  402.  * Bangs in the argument are replaced with the previously entered command.
  403.  * Remember the argument.
  404.  */
  405.     void
  406. do_bang(addr_count, line1, line2, forceit, arg, do_in, do_out)
  407.     int            addr_count;
  408.     linenr_t    line1, line2;
  409.     int            forceit;
  410.     char_u        *arg;
  411.     int            do_in, do_out;
  412. {
  413.     static    char_u    *prevcmd = NULL;        /* the previous command */
  414.     char_u            *newcmd = NULL;            /* the new command */
  415.     int                ins_prevcmd;
  416.     char_u            *t;
  417.     char_u            *p;
  418.     char_u            *trailarg;
  419.     int             len;
  420.     int                scroll_save = msg_scroll;
  421.  
  422.     /*
  423.      * Disallow shell commands from .exrc and .vimrc in current directory for
  424.      * security reasons.
  425.      */
  426.     if (secure)
  427.     {
  428.         secure = 2;
  429.         emsg(e_curdir);
  430.         return;
  431.     }
  432.  
  433.     if (addr_count == 0)                /* :! */
  434.     {
  435.         msg_scroll = FALSE;            /* don't scroll here */
  436.         autowrite_all();
  437.         msg_scroll = scroll_save;
  438.     }
  439.  
  440.     /*
  441.      * Try to find an embedded bang, like in :!<cmd> ! [args]
  442.      * (:!! is indicated by the 'forceit' variable)
  443.      */
  444.     ins_prevcmd = forceit;
  445.     trailarg = arg;
  446.     do
  447.     {
  448.         len = STRLEN(trailarg) + 1;
  449.         if (newcmd != NULL)
  450.             len += STRLEN(newcmd);
  451.         if (ins_prevcmd)
  452.         {
  453.             if (prevcmd == NULL)
  454.             {
  455.                 emsg(e_noprev);
  456.                 vim_free(newcmd);
  457.                 return;
  458.             }
  459.             len += STRLEN(prevcmd);
  460.         }
  461.         if ((t = alloc(len)) == NULL)
  462.         {
  463.             vim_free(newcmd);
  464.             return;
  465.         }
  466.         *t = NUL;
  467.         if (newcmd != NULL)
  468.             STRCAT(t, newcmd);
  469.         if (ins_prevcmd)
  470.             STRCAT(t, prevcmd);
  471.         p = t + STRLEN(t);
  472.         STRCAT(t, trailarg);
  473.         vim_free(newcmd);
  474.         newcmd = t;
  475.  
  476.         /*
  477.          * Scan the rest of the argument for '!', which is replaced by the
  478.          * previous command.  "\!" is replaced by "!" (this is vi compatible).
  479.          */
  480.         trailarg = NULL;
  481.         while (*p)
  482.         {
  483.             if (*p == '!')
  484.             {
  485.                 if (p > newcmd && p[-1] == '\\')
  486.                     vim_memmove(p - 1, p, (size_t)(STRLEN(p) + 1));
  487.                 else
  488.                 {
  489.                     trailarg = p;
  490.                     *trailarg++ = NUL;
  491.                     ins_prevcmd = TRUE;
  492.                     break;
  493.                 }
  494.             }
  495.             ++p;
  496.         }
  497.     } while (trailarg != NULL);
  498.  
  499.     vim_free(prevcmd);
  500.     prevcmd = newcmd;
  501.  
  502.     if (bangredo)            /* put cmd in redo buffer for ! command */
  503.     {
  504.         AppendToRedobuff(prevcmd);
  505.         AppendToRedobuff((char_u *)"\n");
  506.         bangredo = FALSE;
  507.     }
  508.     if (addr_count == 0)                /* :! */
  509.     {
  510.             /* echo the command */
  511.         msg_start();
  512.         msg_outchar(':');
  513.         msg_outchar('!');
  514.         msg_outtrans(prevcmd);
  515.         msg_clr_eos();
  516.         windgoto(msg_row, msg_col);
  517.  
  518.         do_shell(prevcmd); 
  519.     }
  520.     else                                /* :range! */
  521.         do_filter(line1, line2, prevcmd, do_in, do_out);
  522. }
  523.  
  524. /*
  525.  * call a shell to execute a command
  526.  */
  527.     void
  528. do_shell(cmd)
  529.     char_u    *cmd;
  530. {
  531.     BUF        *buf;
  532.     int        save_nwr;
  533.  
  534.     /*
  535.      * Disallow shell commands from .exrc and .vimrc in current directory for
  536.      * security reasons.
  537.      */
  538.     if (secure)
  539.     {
  540.         secure = 2;
  541.         emsg(e_curdir);
  542.         msg_end();
  543.         return;
  544.     }
  545.  
  546. #ifdef WIN32
  547.     /*
  548.      * Check if external commands are allowed now.
  549.      */
  550.     if (can_end_termcap_mode(TRUE) == FALSE)
  551.         return;
  552. #endif
  553.  
  554.     /*
  555.      * For autocommands we want to get the output on the current screen, to
  556.      * avoid having to type return below.
  557.      */
  558.     msg_outchar('\r');                    /* put cursor at start of line */
  559. #ifdef AUTOCMD
  560.     if (!autocmd_busy)
  561. #endif
  562.         stoptermcap();
  563.     msg_outchar('\n');                    /* may shift screen one line up */
  564.  
  565.         /* warning message before calling the shell */
  566.     if (p_warn
  567. #ifdef AUTOCMD
  568.                 && !autocmd_busy
  569. #endif
  570.                                    )
  571.         for (buf = firstbuf; buf; buf = buf->b_next)
  572.             if (buf->b_changed)
  573.             {
  574.                 MSG_OUTSTR("[No write since last change]\n");
  575.                 break;
  576.             }
  577.  
  578. /* This windgoto is required for when the '\n' resulted in a "delete line 1"
  579.  * command to the terminal. */
  580.  
  581.     windgoto(msg_row, msg_col);
  582.     cursor_on();
  583.     (void)call_shell(cmd, SHELL_COOKED);
  584.     need_check_timestamps = TRUE;
  585.  
  586. /*
  587.  * put the message cursor at the end of the screen, avoids wait_return() to
  588.  * overwrite the text that the external command showed
  589.  */
  590.     msg_pos((int)Rows - 1, 0);
  591.  
  592. #ifdef AUTOCMD
  593.     if (!autocmd_busy)
  594. #endif
  595.     {
  596.         /*
  597.          * If K_TI is defined, we assume that we switch screens when
  598.          * starttermcap() is called. In that case we really want to wait for
  599.          * "hit return to continue".
  600.          */
  601.         save_nwr = no_wait_return;
  602.         if (*T_TI != NUL)
  603.             no_wait_return = FALSE;
  604. #ifdef AMIGA
  605.         wait_return(term_console ? -1 : TRUE);        /* see below */
  606. #else
  607.         wait_return(TRUE);
  608. #endif
  609.         no_wait_return = save_nwr;
  610.         starttermcap();        /* start termcap if not done by wait_return() */
  611.  
  612.         /*
  613.          * In an Amiga window redrawing is caused by asking the window size.
  614.          * If we got an interrupt this will not work. The chance that the
  615.          * window size is wrong is very small, but we need to redraw the
  616.          * screen.  Don't do this if ':' hit in wait_return().  THIS IS UGLY
  617.          * but it saves an extra redraw.
  618.          */
  619. #ifdef AMIGA
  620.         if (skip_redraw)                /* ':' hit in wait_return() */
  621.             must_redraw = CLEAR;
  622.         else if (term_console)
  623.         {
  624.             OUTSTR("\033[0 q");         /* get window size */
  625.             if (got_int)
  626.                 must_redraw = CLEAR;    /* if got_int is TRUE, redraw needed */
  627.             else
  628.                 must_redraw = 0;        /* no extra redraw needed */
  629.         }
  630. #endif /* AMIGA */
  631.     }
  632. #ifdef AUTOCMD
  633.     else
  634.         must_redraw = CLEAR;
  635. #endif
  636. }
  637.  
  638. /*
  639.  * do_filter: filter lines through a command given by the user
  640.  *
  641.  * We use temp files and the call_shell() routine here. This would normally
  642.  * be done using pipes on a UNIX machine, but this is more portable to
  643.  * non-unix machines. The call_shell() routine needs to be able
  644.  * to deal with redirection somehow, and should handle things like looking
  645.  * at the PATH env. variable, and adding reasonable extensions to the
  646.  * command name given by the user. All reasonable versions of call_shell()
  647.  * do this.
  648.  * We use input redirection if do_in is TRUE.
  649.  * We use output redirection if do_out is TRUE.
  650.  */
  651.     void
  652. do_filter(line1, line2, buff, do_in, do_out)
  653.     linenr_t    line1, line2;
  654.     char_u        *buff;
  655.     int            do_in, do_out;
  656. {
  657. #ifdef USE_TMPNAM
  658.     char_u        itmp[L_tmpnam];        /* use tmpnam() */
  659.     char_u        otmp[L_tmpnam];
  660. #else
  661.     char_u        itmp[TMPNAMELEN];
  662.     char_u        otmp[TMPNAMELEN];
  663. #endif
  664.     linenr_t     linecount;
  665.     FPOS        cursor_save;
  666.  
  667.     /*
  668.      * Disallow shell commands from .exrc and .vimrc in current directory for
  669.      * security reasons.
  670.      */
  671.     if (secure)
  672.     {
  673.         secure = 2;
  674.         emsg(e_curdir);
  675.         return;
  676.     }
  677.     if (*buff == NUL)        /* no filter command */
  678.         return;
  679.  
  680. #ifdef WIN32
  681.     /*
  682.      * Check if external commands are allowed now.
  683.      */
  684.     if (can_end_termcap_mode(TRUE) == FALSE)
  685.         return;
  686. #endif
  687.  
  688.     cursor_save = curwin->w_cursor;
  689.     linecount = line2 - line1 + 1;
  690.     curwin->w_cursor.lnum = line1;
  691.     curwin->w_cursor.col = 0;
  692.  
  693.     /*
  694.      * 1. Form temp file names
  695.      * 2. Write the lines to a temp file
  696.      * 3. Run the filter command on the temp file
  697.      * 4. Read the output of the command into the buffer
  698.      * 5. Delete the original lines to be filtered
  699.      * 6. Remove the temp files
  700.      */
  701.  
  702. #ifndef USE_TMPNAM         /* tmpnam() will make its own name */
  703. # ifdef OS2
  704.     check_tmpenv();
  705.     expand_env(TMPNAME1, itmp, TMPNAMELEN);
  706.     expand_env(TMPNAME2, otmp, TMPNAMELEN);
  707. # else
  708.     STRCPY(itmp, TMPNAME1);
  709.     STRCPY(otmp, TMPNAME2);
  710. # endif
  711. #endif
  712.  
  713.     if ((do_in && *mktemp((char *)itmp) == NUL) ||
  714.                                      (do_out && *mktemp((char *)otmp) == NUL))
  715.     {
  716.         emsg(e_notmp);
  717.         return;
  718.     }
  719.  
  720. /*
  721.  * The writing and reading of temp files will not be shown.
  722.  * Vi also doesn't do this and the messages are not very informative.
  723.  */
  724.     ++no_wait_return;            /* don't call wait_return() while busy */
  725.     if (do_in && buf_write(curbuf, itmp, NULL, line1, line2,
  726.                                               FALSE, 0, FALSE, TRUE) == FAIL)
  727.     {
  728.         msg_outchar('\n');                    /* keep message from buf_write() */
  729.         --no_wait_return;
  730.         (void)emsg2(e_notcreate, itmp);        /* will call wait_return */
  731.         goto filterend;
  732.     }
  733.     if (!do_out)
  734.         msg_outchar('\n');
  735.  
  736. #if (defined(UNIX) && !defined(ARCHIE)) || defined(OS2)
  737. /*
  738.  * put braces around the command (for concatenated commands)
  739.  */
  740.      sprintf((char *)IObuff, "(%s)", (char *)buff);
  741.     if (do_in)
  742.     {
  743.         STRCAT(IObuff, " < ");
  744.         STRCAT(IObuff, itmp);
  745.     }
  746. #else
  747. /*
  748.  * for shells that don't understand braces around commands, at least allow
  749.  * the use of commands in a pipe.
  750.  */
  751.     STRCPY(IObuff, buff);
  752.     if (do_in)
  753.     {
  754.         char_u        *p;
  755.     /*
  756.      * If there is a pipe, we have to put the '<' in front of it
  757.      */
  758.         p = vim_strchr(IObuff, '|');
  759.         if (p)
  760.             *p = NUL;
  761.         STRCAT(IObuff, " < ");
  762.         STRCAT(IObuff, itmp);
  763.         p = vim_strchr(buff, '|');
  764.         if (p)
  765.             STRCAT(IObuff, p);
  766.     }
  767. #endif
  768.     if (do_out)
  769.     {
  770.         char_u *p;
  771.  
  772.         if ((p = vim_strchr(p_srr, '%')) != NULL && p[1] == 's')
  773.         {
  774.             p = IObuff + STRLEN(IObuff);
  775.             *p++ = ' '; /* not really needed? Not with sh, ksh or bash */
  776.             sprintf((char *)p, (char *)p_srr, (char *)otmp);
  777.         }
  778.         else
  779.             sprintf((char *)IObuff + STRLEN(IObuff), " %s %s",
  780.                                                  (char *)p_srr, (char *)otmp);
  781.     }
  782.  
  783.     windgoto((int)Rows - 1, 0);
  784.     cursor_on();
  785.  
  786.     /*
  787.      * When not redirecting the output the command can write anything to the
  788.      * screen. If 'shellredir' is equal to ">", screen may be messed up by
  789.      * stderr output of external command. Clear the screen later.
  790.      * If do_in is FALSE, this could be something like ":r !cat", which may
  791.      * also mess up the screen, clear it later.
  792.      */
  793.     if (!do_out || STRCMP(p_srr, ">") == 0 || !do_in)
  794.         must_redraw = CLEAR;
  795.     else
  796.         redraw_later(NOT_VALID);
  797.  
  798.     /*
  799.      * When call_shell() fails wait_return() is called to give the user a
  800.      * chance to read the error messages. Otherwise errors are ignored, so you
  801.      * can see the error messages from the command that appear on stdout; use
  802.      * 'u' to fix the text
  803.      * Switch to cooked mode when not redirecting stdin, avoids that something
  804.      * like ":r !cat" hangs.
  805.      */
  806.     if (call_shell(IObuff, SHELL_FILTER | SHELL_COOKED) == FAIL)
  807.     {
  808.         must_redraw = CLEAR;
  809.         wait_return(FALSE);
  810.     }
  811.     need_check_timestamps = TRUE;
  812.  
  813.     if (do_out)
  814.     {
  815.         if (u_save((linenr_t)(line2), (linenr_t)(line2 + 1)) == FAIL)
  816.         {
  817.             goto error;
  818.         }
  819.         if (readfile(otmp, NULL, line2, FALSE, (linenr_t)0, MAXLNUM, TRUE)
  820.                                                                       == FAIL)
  821.         {
  822.             msg_outchar('\n');
  823.             emsg2(e_notread, otmp);
  824.             goto error;
  825.         }
  826.  
  827.         if (do_in)
  828.         {
  829.             /* put cursor on first filtered line for ":range!cmd" */
  830.             curwin->w_cursor.lnum = line1;
  831.             dellines(linecount, TRUE, TRUE);
  832.             curbuf->b_op_start.lnum -= linecount;        /* adjust '[ */
  833.             curbuf->b_op_end.lnum -= linecount;            /* adjust '] */
  834.         }
  835.         else
  836.         {
  837.             /* put cursor on last new line for ":r !cmd" */
  838.             curwin->w_cursor.lnum = curbuf->b_op_end.lnum;
  839.             linecount = curbuf->b_op_end.lnum - curbuf->b_op_start.lnum + 1;
  840.         }
  841.         beginline(TRUE);                /* cursor on first non-blank */
  842.         --no_wait_return;
  843.  
  844.         if (linecount > p_report)
  845.         {
  846.             if (do_in)
  847.             {
  848.                 sprintf((char *)msg_buf, "%ld lines filtered", (long)linecount);
  849.                 if (msg(msg_buf) && !msg_scroll)
  850.                     keep_msg = msg_buf;        /* display message after redraw */
  851.             }
  852.             else
  853.                 msgmore((long)linecount);
  854.         }
  855.     }
  856.     else
  857.     {
  858. error:
  859.         /* put cursor back in same position for ":w !cmd" */
  860.         curwin->w_cursor = cursor_save;
  861.         --no_wait_return;
  862.         wait_return(FALSE);
  863.     }
  864.  
  865. filterend:
  866.     vim_remove(itmp);
  867.     vim_remove(otmp);
  868. }
  869.  
  870. #ifdef OS2
  871. /*
  872.  * If $TMP is not defined, construct a sensible default.
  873.  * This is required for TMPNAME1 and TMPNAME2 to work.
  874.  */
  875.     static void
  876. check_tmpenv()
  877. {
  878.     char_u    *envent;
  879.  
  880.     if (getenv("TMP") == NULL)
  881.     {
  882.         envent = alloc(8);
  883.         if (envent != NULL)
  884.         {
  885.             strcpy(envent, "TMP=C:/");
  886.             putenv(envent);
  887.         }
  888.     }
  889. }
  890. #endif /* OS2 */
  891.  
  892. #ifdef VIMINFO
  893.  
  894. static int no_viminfo __ARGS((void));
  895.  
  896.     static int
  897. no_viminfo()
  898. {
  899.     /* "vim -i NONE" does not read or write a viminfo file */
  900.     return (use_viminfo != NULL && STRCMP(use_viminfo, "NONE") == 0);
  901. }
  902.  
  903. /*
  904.  * read_viminfo() -- Read the viminfo file.  Registers etc. which are already
  905.  * set are not over-written unless force is TRUE. -- webb
  906.  */
  907.     int
  908. read_viminfo(file, want_info, want_marks, force)
  909.     char_u    *file;
  910.     int        want_info;
  911.     int        want_marks;
  912.     int        force;
  913. {
  914.     FILE    *fp;
  915.  
  916.     if (no_viminfo())
  917.         return FAIL;
  918.  
  919.     file = viminfo_filename(file);            /* may set to default if NULL */
  920.     if ((fp = fopen((char *)file, READBIN)) == NULL)
  921.         return FAIL;
  922.  
  923.     do_viminfo(fp, NULL, want_info, want_marks, force);
  924.  
  925.     fclose(fp);
  926.  
  927.     return OK;
  928. }
  929.  
  930. /*
  931.  * write_viminfo() -- Write the viminfo file.  The old one is read in first so
  932.  * that effectively a merge of current info and old info is done.  This allows
  933.  * multiple vims to run simultaneously, without losing any marks etc.  If
  934.  * force is TRUE, then the old file is not read in, and only internal info is
  935.  * written to the file. -- webb
  936.  */
  937.     void
  938. write_viminfo(file, force)
  939.     char_u    *file;
  940.     int        force;
  941. {
  942.     FILE    *fp_in = NULL;
  943.     FILE    *fp_out = NULL;
  944. #ifdef USE_TMPNAM
  945.     char_u    tmpname[L_tmpnam];        /* use tmpnam() */
  946. #else
  947.     char_u    tmpname[TMPNAMELEN];
  948. #endif
  949.  
  950.     if (no_viminfo())
  951.         return;
  952.  
  953. #ifndef USE_TMPNAM         /* tmpnam() will make its own name */
  954. # ifdef OS2
  955.     check_tmpenv();
  956.     expand_env(TMPNAME2, tmpname, TMPNAMELEN);
  957. # else
  958.     STRCPY(tmpname, TMPNAME2);
  959. # endif
  960. #endif
  961.  
  962.     file = viminfo_filename(file);        /* may set to default if NULL */
  963.     file = strsave(file);                /* make a copy, don't want NameBuff */
  964.     if (file != NULL)
  965.     {
  966.         fp_in = fopen((char *)file, READBIN);
  967.         if (fp_in == NULL)
  968.             fp_out = fopen((char *)file, WRITEBIN);
  969.         else if (*mktemp((char *)tmpname) != NUL)
  970.             fp_out = fopen((char *)tmpname, WRITEBIN);
  971.     }
  972.     if (file == NULL || fp_out == NULL)
  973.     {
  974.         EMSG2("Can't write viminfo file %s!", file == NULL ? (char_u *)"" :
  975.                                               fp_in == NULL ? file : tmpname);
  976.         if (fp_in != NULL)
  977.             fclose(fp_in);
  978.         vim_free(file);
  979.         return;
  980.     }
  981.  
  982.     do_viminfo(fp_in, fp_out, !force, !force, FALSE);
  983.  
  984.     fclose(fp_out);            /* errors are ignored !? */
  985.     if (fp_in != NULL)
  986.     {
  987.         fclose(fp_in);
  988.         if (vim_rename(tmpname, file) == -1)
  989.             vim_remove(tmpname);
  990.     }
  991.     vim_free(file);
  992. }
  993.  
  994.     static char_u *
  995. viminfo_filename(file)
  996.     char_u        *file;
  997. {
  998.     if (file == NULL || *file == NUL)
  999.     {
  1000.         expand_env(use_viminfo == NULL ? (char_u *)VIMINFO_FILE : use_viminfo,
  1001.                                                           NameBuff, MAXPATHL);
  1002.         return NameBuff;
  1003.     }
  1004.     return file;
  1005. }
  1006.  
  1007. /*
  1008.  * do_viminfo() -- Should only be called from read_viminfo() & write_viminfo().
  1009.  */
  1010.     static void
  1011. do_viminfo(fp_in, fp_out, want_info, want_marks, force_read)
  1012.     FILE    *fp_in;
  1013.     FILE    *fp_out;
  1014.     int        want_info;
  1015.     int        want_marks;
  1016.     int        force_read;
  1017. {
  1018.     int        count = 0;
  1019.     int        eof = FALSE;
  1020.     char_u    *line;
  1021.  
  1022.     if ((line = alloc(LSIZE)) == NULL)
  1023.         return;
  1024.  
  1025.     if (fp_in != NULL)
  1026.     {
  1027.         if (want_info)
  1028.             eof = read_viminfo_up_to_marks(line, fp_in, force_read);
  1029.         else
  1030.             /* Skip info, find start of marks */
  1031.             while (!(eof = vim_fgets(line, LSIZE, fp_in)) && line[0] != '>')
  1032.                 ;
  1033.     }
  1034.     if (fp_out != NULL)
  1035.     {
  1036.         /* Write the info: */
  1037.         fprintf(fp_out, "# This viminfo file was generated by vim\n");
  1038.         fprintf(fp_out, "# You may edit it if you're careful!\n\n");
  1039.         write_viminfo_search_pattern(fp_out);
  1040.         write_viminfo_sub_string(fp_out);
  1041.         write_viminfo_history(fp_out);
  1042.         write_viminfo_registers(fp_out);
  1043.         write_viminfo_filemarks(fp_out);
  1044.         count = write_viminfo_marks(fp_out);
  1045.     }
  1046.     if (fp_in != NULL && want_marks)
  1047.         copy_viminfo_marks(line, fp_in, fp_out, count, eof);
  1048.     vim_free(line);
  1049. }
  1050.  
  1051. /*
  1052.  * read_viminfo_up_to_marks() -- Only called from do_viminfo().  Reads in the
  1053.  * first part of the viminfo file which contains everything but the marks that
  1054.  * are local to a file.  Returns TRUE when end-of-file is reached. -- webb
  1055.  */
  1056.     static int
  1057. read_viminfo_up_to_marks(line, fp, force)
  1058.     char_u    *line;
  1059.     FILE    *fp;
  1060.     int        force;
  1061. {
  1062.     int        eof;
  1063.  
  1064.     prepare_viminfo_history(force ? 9999 : 0);
  1065.     eof = vim_fgets(line, LSIZE, fp);
  1066.     while (!eof && line[0] != '>')
  1067.     {
  1068.         switch (line[0])
  1069.         {
  1070.             case NUL:
  1071.             case '\r':
  1072.             case '\n':
  1073.             case '#':        /* A comment */
  1074.                 eof = vim_fgets(line, LSIZE, fp);
  1075.                 break;
  1076.             case '"':
  1077.                 eof = read_viminfo_register(line, fp, force);
  1078.                 break;
  1079.             case '/':        /* Search string */
  1080.             case '&':        /* Substitute search string */
  1081.             case '~':        /* Last search string, followed by '/' or '&' */
  1082.                 eof = read_viminfo_search_pattern(line, fp, force);
  1083.                 break;
  1084.             case '$':
  1085.                 eof = read_viminfo_sub_string(line, fp, force);
  1086.                 break;
  1087.             case ':':
  1088.             case '?':
  1089.                 eof = read_viminfo_history(line, fp);
  1090.                 break;
  1091.             case '\'':
  1092.                 /* How do we have a file mark when the file is not in the
  1093.                  * buffer list?
  1094.                  */
  1095.                 eof = read_viminfo_filemark(line, fp, force);
  1096.                 break;
  1097. #if 0
  1098.             case '+':
  1099.                 /* eg: "+40 /path/dir file", for running vim with no args */
  1100.                 eof = vim_fgets(line, LSIZE, fp);
  1101.                 break;
  1102. #endif
  1103.             default:
  1104.                 EMSG2("viminfo: Illegal starting char in line %s", line);
  1105.                 eof = vim_fgets(line, LSIZE, fp);
  1106.                 break;
  1107.         }
  1108.     }
  1109.     finish_viminfo_history();
  1110.     return eof;
  1111. }
  1112.  
  1113. /*
  1114.  * check string read from viminfo file
  1115.  * remove '\n' at the end of the line
  1116.  * - replace CTRL-V CTRL-V with CTRL-V
  1117.  * - replace CTRL-V 'n'    with '\n'
  1118.  */
  1119.     void
  1120. viminfo_readstring(p)
  1121.     char_u        *p;
  1122. {
  1123.     while (*p != NUL && *p != '\n')
  1124.     {
  1125.         if (*p == Ctrl('V'))
  1126.         {
  1127.             if (p[1] == 'n')
  1128.                 p[0] = '\n';
  1129.             vim_memmove(p + 1, p + 2, STRLEN(p));
  1130.         }
  1131.         ++p;
  1132.     }
  1133.     *p = NUL;
  1134. }
  1135.  
  1136. /*
  1137.  * write string to viminfo file
  1138.  * - replace CTRL-V with CTRL-V CTRL-V
  1139.  * - replace '\n'   with CTRL-V 'n'
  1140.  * - add a '\n' at the end
  1141.  */
  1142.     void
  1143. viminfo_writestring(fd, p)
  1144.     FILE    *fd;
  1145.     char_u    *p;
  1146. {
  1147.     register int    c;
  1148.  
  1149.     while ((c = *p++) != NUL)
  1150.     {
  1151.         if (c == Ctrl('V') || c == '\n')
  1152.         {
  1153.             putc(Ctrl('V'), fd);
  1154.             if (c == '\n')
  1155.                 c = 'n';
  1156.         }
  1157.         putc(c, fd);
  1158.     }
  1159.     putc('\n', fd);
  1160. }
  1161. #endif /* VIMINFO */
  1162.  
  1163. /*
  1164.  * Implementation of ":fixdel", also used by get_stty().
  1165.  *  <BS>    resulting <Del>
  1166.  *   ^?        ^H
  1167.  * not ^?      ^?
  1168.  */
  1169.     void
  1170. do_fixdel()
  1171. {
  1172.     char_u    *p;
  1173.  
  1174.     p = find_termcode((char_u *)"kb");
  1175.     add_termcode((char_u *)"kD", p != NULL && *p == 0x7f ?
  1176.                                          (char_u *)"\010" : (char_u *)"\177");
  1177. }
  1178.  
  1179.     void
  1180. print_line(lnum, use_number)
  1181.     linenr_t    lnum;
  1182.     int            use_number;
  1183. {
  1184.     char_u        numbuf[20];
  1185.  
  1186.     msg_outchar('\n');
  1187.     if (curwin->w_p_nu || use_number)
  1188.     {
  1189.         sprintf((char *)numbuf, "%7ld ", (long)lnum);
  1190.         set_highlight('n');        /* Highlight line numbers */
  1191.         start_highlight();
  1192.         msg_outstr(numbuf);
  1193.         stop_highlight();
  1194.     }
  1195.     msg_prt_line(ml_get(lnum));
  1196. }
  1197.  
  1198. /*
  1199.  * Implementation of ":file [fname]".
  1200.  */
  1201.     void
  1202. do_file(arg, forceit)
  1203.     char_u    *arg;
  1204.     int        forceit;
  1205. {
  1206.     char_u        *fname, *sfname;
  1207.     BUF            *buf;
  1208.  
  1209.     if (*arg != NUL)
  1210.     {
  1211.         /*
  1212.          * The name of the current buffer will be changed.
  1213.          * A new buffer entry needs to be made to hold the old
  1214.          * file name, which will become the alternate file name.
  1215.          */
  1216.         fname = curbuf->b_filename;
  1217.         sfname = curbuf->b_sfilename;
  1218.         curbuf->b_filename = NULL;
  1219.         curbuf->b_sfilename = NULL;
  1220.         if (setfname(arg, NULL, TRUE) == FAIL)
  1221.         {
  1222.             curbuf->b_filename = fname;
  1223.             curbuf->b_sfilename = sfname;
  1224.             return;
  1225.         }
  1226.         curbuf->b_notedited = TRUE;
  1227.         buf = buflist_new(fname, sfname, curwin->w_cursor.lnum, FALSE);
  1228.         if (buf != NULL)
  1229.             curwin->w_alt_fnum = buf->b_fnum;
  1230.         vim_free(fname);
  1231.         vim_free(sfname);
  1232.     }
  1233.     /* print full filename if :cd used */
  1234.     fileinfo(did_cd, FALSE, forceit);
  1235. }
  1236.